package com.example.tcpassistant;

import static com.example.tcpassistant.TCPService.socket;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.DataSetObserver;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    AlertDialog dialog;                 //弹窗
    View.OnClickListener listener;      //弹窗监听
    String ipaddress,port,history_data="",text;
    boolean connected=false,tcp_server=true;//默认为TCP Service 模式，断开连接

    TextView textView_tip,textView_connect_status;
    ImageView imageView_connect_status;
    ImageButton imageButton_clean,imageButton_senddata;
    EditText editText_senddata;
    ListView listView;

    public cmdReceiver cmdReceiver;                         //网络事件接收器
    private List<Bean> data = new ArrayList<>();//ArrayList 类是一个可以动态修改的数组，与普通数组的区别就是它是没有固定大小的限制，我们可以添加或删除元素

    ServerSocket serverSocket;
    Handler handler;
    private PrintWriter pw;

    private OutputStream tcp_outputStream = null;
    private InputStream tcp_inputStream = null;
    Socket tcp_client_socket = null;//等待客户端连接
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        setContentView(R.layout.activity_main);
        handler = new Handler();

        textView_tip=(TextView)findViewById(R.id.textView_tip); //必须写在 super.onCreate(savedInstanceState);之后。否则闪退
        imageView_connect_status=(ImageView)findViewById(R.id.imageView_connect_status);
        textView_connect_status=(TextView)findViewById(R.id.textView_connect_status);
        imageButton_clean=(ImageButton)findViewById(R.id.imageButton_clean);
        imageButton_senddata=(ImageButton)findViewById(R.id.imageButton_senddata);
        editText_senddata=(EditText)findViewById(R.id.editText_senddata);
        listView = findViewById(R.id.lv);

        imageButton_clean.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                history_data="";        //清除接收缓冲区域
                textView_tip.setText(R.string.wait_get_information);
                data = new ArrayList<>();   //清除旧数据缓存区
                MyAdapter adapter_new=new MyAdapter(data,getApplication());//Adapter作用将各种数据以合适的形式显示在View中给用户看
                listView.setAdapter(adapter_new);
            }
        });
        imageButton_senddata.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(connected){
                    if(tcp_server==false) {
                        TCPService.sendStr(String.valueOf(editText_senddata.getText()));
                        Toast.makeText(getApplicationContext(), "已发送", Toast.LENGTH_SHORT).show();
                    }
                    else
                    {
                        new Thread(new Runnable() {
                            OutputStream os = null;
                            @Override
                            public void run()
                            {
                                try {
                                    os = tcp_client_socket.getOutputStream();
                                    String text=String.valueOf(editText_senddata.getText());
                                    if(!(text.isEmpty()))
                                    {
                                        try {
                                            os.write(text.getBytes());
                                            Looper.prepare();//解除Android不允许在子线程中弹出 Toast 提示的限制
                                            Toast.makeText(getApplicationContext(), "已发送", Toast.LENGTH_SHORT).show();
                                            Looper.loop(); //恢复限制
                                        } catch (IOException e)
                                        {
                                            e.printStackTrace();
                                        }
                                    }
                                    else
                                    {
                                        Looper.prepare();//解除Android不允许在子线程中弹出 Toast 提示的限制
                                        Toast.makeText(getApplicationContext(), "请先输入要发送的数据", Toast.LENGTH_SHORT).show();
                                        Looper.loop();//恢复限制
                                    }
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }).start();
                    }
                }
                else
                    Toast.makeText(getApplicationContext(),"请先建立TCP连接", Toast.LENGTH_SHORT).show();
            }
        });
        //注册广播接收器
        cmdReceiver =new cmdReceiver();
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction("com.example.communication.data");
        getApplication().registerReceiver(cmdReceiver,intentFilter);
        alertSignTable_change_tcpmode();
    }
    /**
     * @Description 弹出输入IP地址和端口界面。
     */
    public void alertSignTable() {
        LayoutInflater fac = LayoutInflater.from(MainActivity.this);
        View alertView = fac.inflate(R.layout.pop_up_input, null);

        dialog = new AlertDialog.Builder(MainActivity.this)
                .setView(alertView)
                .create();
        dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
        dialog.show();

        Button btn_confirm = dialog.getWindow().findViewById(R.id.btn_confirm);
        Button btn_cancel = dialog.getWindow().findViewById(R.id.btn_cancel);
        EditText edit_ipadress = dialog.getWindow().findViewById(R.id.edt_ipaddress);
        EditText edit_port = dialog.getWindow().findViewById(R.id.edt_com);
        TextView textView_inputip_tcpmode = dialog.getWindow().findViewById(R.id.textView_input_ipport_tcpmode);

        if (tcp_server == true){
            textView_inputip_tcpmode.setText(R.string.tcp_mode_now_service);
            ipaddress=getIPAddress();
            if(ipaddress==null)
                edit_ipadress.setHint("当前无网络,请完成网络连接"+"\r\n(TCP Server模式下采用本机IP地址，不可修改)");
            else
                edit_ipadress.setHint(ipaddress+"\r\n(TCP Server模式下采用本机IP地址，不可修改)");
            //设置为不可输入
            edit_ipadress.setFocusable(false);
            edit_ipadress.setFocusableInTouchMode(false); // user touches widget on phone with touch screen
            edit_ipadress.setClickable(false); // user navigates with wheel and selects widget
        }
        else
        {
            textView_inputip_tcpmode.setText(R.string.tcp_mode_now_client);
            //设置为可输入
            edit_ipadress.setFocusable(true);
            edit_ipadress.setFocusableInTouchMode(true); // user touches widget on phone with touch screen
            edit_ipadress.setClickable(true); // user navigates with wheel and selects widget
        }
        btn_confirm.setOnClickListener(listener);
        btn_cancel.setOnClickListener(listener);

        btn_confirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                port = edit_port.getText().toString();
                if(tcp_server==true) {
                    ipaddress = getIPAddress();
                    try {
                        startServer();
                        new NewThread_wait_tcpclient().start();//启动线程
                        dialog.dismiss();

                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
                else
                {
                    ipaddress = edit_ipadress.getText().toString();
                    if((!(TextUtils.isEmpty(ipaddress)))&&(!(TextUtils.isEmpty(ipaddress))))
                    {
                            Intent mIntent = new Intent(getApplication(), TCPService.class);
                            mIntent.putExtra("ipaddress", ipaddress);
                            mIntent.putExtra("port", port);
                            getApplication().startService(mIntent);
                            dialog.dismiss();
                            set_connected(true);
                    }
                    else
                    {
                        Toast.makeText(getApplicationContext(), "请输入IP地址与端口号", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });
        btn_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
    }
    /**
     * @Description 弹出TCPMode界面。
     */
    public void alertSignTable_change_tcpmode() {
        LayoutInflater fac = LayoutInflater.from(MainActivity.this);
        View alertView = fac.inflate(R.layout.pop_change_mode, null);

        dialog = new AlertDialog.Builder(MainActivity.this)
                .setView(alertView)
                .create();
        dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
        dialog.show();
        Button btn_tcp_server = dialog.getWindow().findViewById(R.id.btn_tcp_server);
        Button btn_tcp_client = dialog.getWindow().findViewById(R.id.btn_tcp_client);
        TextView textView_tcpmode_stutus=dialog.getWindow().findViewById(R.id.textView_tcpmode_stutus);

        if(tcp_server==true)
            textView_tcpmode_stutus.setText(R.string.tcp_mode_now_service);
        else
            textView_tcpmode_stutus.setText(R.string.tcp_mode_now_client);

        btn_tcp_server.setOnClickListener(listener);
        btn_tcp_client.setOnClickListener(listener);

        btn_tcp_server.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tcp_server=true;
                Toast.makeText(getApplicationContext(),"TCP Server 模式", Toast.LENGTH_SHORT).show();
                dialog.dismiss();
                alertSignTable();
            }
        });
        btn_tcp_client.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tcp_server=false;
                Toast.makeText(getApplicationContext(),"TCP Client 模式", Toast.LENGTH_SHORT).show();
                dialog.dismiss();
                alertSignTable();
            }
        });
    }
    /**
     * @Description 弹出"关于"信息介绍界面。
     */
    public void alertSignTable_about() {
        LayoutInflater fac = LayoutInflater.from(MainActivity.this);
        View alertView = fac.inflate(R.layout.pop_about, null);

        dialog = new AlertDialog.Builder(MainActivity.this)
                .setView(alertView)
                .create();
        dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
        dialog.show();
    }
    /**
     * @Description 重写获取菜单项的方法
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater=getMenuInflater();//获取菜单Inflater,MenuInflater加载menu布局文件
        inflater.inflate(R.menu.pop_input,menu);//通过inflate获取菜单资源
        return true;
    }
    /**
     * @Description 列表选择
     */
    public boolean onOptionsItemSelected (MenuItem item) {
        switch (item.getItemId()) {
            case R.id.item0_mode:
               // Toast.makeText(this, "切换TCP工作模式", Toast.LENGTH_SHORT).show();
                alertSignTable_change_tcpmode();
                break;
            case R.id.item1_connect:
                //Toast.makeText(this, "连接/断开", Toast.LENGTH_SHORT).show();
                if(connected==false)
                    alertSignTable();
                else
                {
                    dialog.dismiss();
                    Toast.makeText(this,"当前设备已连接，确定断开连接吗？", Toast.LENGTH_SHORT).show();
                    CloseDialog(1);
                }
                break;
            case R.id.item2_exit_app:
                Toast.makeText(this,"退出应用", Toast.LENGTH_SHORT).show();
                CloseDialog(2);
                break;
            case R.id.item3_about:
                alertSignTable_about();
                break;
            default:
        }
        return true;
    }
    /**
     * @Description 弹出关闭应用的对话窗口
     */
    public void CloseDialog(int fun) {
        String tip_title="title",tip_con="conent";
        switch(fun)
        {
            case 1:
                tip_title="断开连接";
                tip_con="当前设备已连接，确定断开连接吗？";
                break;
            case 2:
                tip_title="退出应用";
                tip_con="确定退出应用吗？";
                break;
        }
        //创造一个builder的构造器
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        //设置标题、设置图片、设置消息内容、设置setPositiveButton确定按钮（当点击OK后，new是要去做啥事情）
        builder.setTitle(tip_title)
                .setIcon(R.drawable.author)
                .setMessage(tip_con)
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        switch(fun)
                        {
                            case 1:
                                TCPService.sendStr("APP:byebye");
                                //设置需要弹出对话框信息
                                Toast.makeText(MainActivity.this,"连接已断开",Toast.LENGTH_SHORT).show();
                                set_connected(false);
                                try {
                                    TCPService.disconnected();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                                break;
                            case 2:
                                //设置需要弹出对话框信息
                                Toast.makeText(MainActivity.this,"应用已退出",Toast.LENGTH_SHORT).show();
                                finish();
                                System.exit(0);
                                break;
                        }

                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {//设置需要弹出对话框信息
                        // Toast.makeText(MainActivity.this,"取消",Toast.LENGTH_SHORT).show();
                    }
                });
        AlertDialog ad = builder.create();
        ad.show();
    }
    /**
     * @Description 修改连接状态
     */
    public void set_connected(boolean i)
    {
        connected=i;
        if(connected)
        {
            imageView_connect_status.setImageDrawable(getResources().getDrawable(R.drawable.light_on));
            textView_connect_status.setText("已连接");
            textView_tip.setText(R.string.wait_get_information);
        }
        else
        {
            imageView_connect_status.setImageDrawable(getResources().getDrawable(R.drawable.light_off));
            textView_connect_status.setText("未连接");
            textView_tip.setText(R.string.wait_dev_connect);
        }
    }
    /**
     * @Description 接收数据
     */
    public class cmdReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String recieveData=intent.getStringExtra("data");   //用于保存接收的数据
            DataHandle(recieveData);
        }
    }
    /**
     * @Description 数据处理
     */
    public void DataHandle(String RecvData)
    {
        String str_temp;
        if(RecvData!=null)
        {
            textView_tip.setText("接收到数据："+RecvData);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
            Date time_date = new Date(System.currentTimeMillis());
            add_display_recvdata("["+simpleDateFormat.format(time_date)+"]:"+RecvData);
            //数据解析
//          str_temp=RecvData.substring(0,4);//截取0,1,2,3,即前四位
//            if(str_temp.equals("ESP:"))
//            {
//                textView_tip.setText("接收到ESP8266数据:"+RecvData);
//                str_temp=RecvData.substring(4,6);//截取4,5位
//                //SMB:BT99
//            }
        }
    }
    /**
     * @Description 将接收到的数据添加列表项
     */
    public void add_display_recvdata(String reccdata)
    {
        Bean bean = new Bean();
        bean.setName(reccdata);
        data.add(bean);//通过add把数据加入到data里面
        MyAdapter adapter=new MyAdapter(data,this);//Adapter作用将各种数据以合适的形式显示在View中给用户看
        listView.setAdapter(adapter);//Adapter作用将各种数据以合适的形式显示在View中给用户看
        listView.setSelection(adapter.getCount()-1);
    }
    /*********************************************TCP创建服务器部分*************************************************************/
    /**
     * @Description 获取设备的接入的wifi或流量网络的IP地址。
     */
    String getIPAddress() {
        Context context=MainActivity.this;
        NetworkInfo info = ((ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        if (info != null && info.isConnected()) {
            //流量网络
            if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
                try {
                    for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); )
                    {
                        NetworkInterface intf = en.nextElement();
                        for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); )
                        {
                            InetAddress inetAddress = enumIpAddr.nextElement();
                            if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                                return inetAddress.getHostAddress();
                            }
                        }
                    }
                } catch (SocketException e) {
                    e.printStackTrace();
                }
            }
            //wifi网络
            else if (info.getType() == ConnectivityManager.TYPE_WIFI)
            {
                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                //调用方法将int转换为地址字符串
                String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址
                return ipAddress;
            }
        }
        else
        {
            Toast.makeText(this,"请先连接网络", Toast.LENGTH_SHORT).show();
        }
        return null;
    }
    /**
     * @Description int类型IP转换为String类型
     */
    String intIP2StringIP(int ip) {
        return (ip & 0xFF) + "." +
                ((ip >> 8) & 0xFF) + "." +
                ((ip >> 16) & 0xFF) + "." +
                (ip >> 24 & 0xFF);
    }
    /**
     * 创建TCP服务器
     */
    void startServer() throws IOException {

        serverSocket = new ServerSocket(Integer.parseInt(port));
        Toast.makeText(this, "服务开启", Toast.LENGTH_LONG).show();
    }
    /**
     * 创建子线程等待客户端接入
     */
    class NewThread_wait_tcpclient extends Thread {
        OutputStream os;
        @Override
        public void run() {
            while (true) {
                System.out.println("–等待客户端连接–");
                try {
                    tcp_client_socket = serverSocket.accept();
                    System.out.println("得到客户端连接：" + socket);
                    os = tcp_client_socket.getOutputStream();
                    String client_ip=tcp_client_socket.getInetAddress().toString();
                    new Thread(){
                        @Override
                        public void run() {
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    textView_connect_status.setText("Client:"+client_ip+"已连接");
                                    connected=true;
                                    imageView_connect_status.setImageDrawable(getResources().getDrawable(R.drawable.light_on));
                                }
                            });
                        }
                    }.start();
                    String text = "Hello, I am TCP Server";
                    os.write(text.getBytes());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Receive_Thread receive_Thread = new Receive_Thread();
                receive_Thread.start();
            }
        }
    }
    /**
     * 创建子线程接收客户端数据并处理
     */
    class Receive_Thread extends Thread {
        public void run()
        {
            System.out.println("in");
            if (null != tcp_client_socket) {
                try {
                    while (true) {
                        final byte[] buffer = new byte[1024];
                        tcp_inputStream = tcp_client_socket.getInputStream();
                        final int len = tcp_inputStream.read(buffer);
                        if (len == -1) {
                            tcp_client_socket.close();
                            tcp_client_socket = null;
                            connected = false;
                            runOnUiThread(new Runnable()
                            {
                                public void run() {
                                    textView_tip.setText(R.string.wait_dev_connect);
                                    textView_connect_status.setText("未连接");
                                    history_data="";        //清除接收缓冲区域
                                    editText_senddata.setText("");
                                    textView_tip.setText(R.string.wait_get_information);
                                    data = new ArrayList<>();   //清除旧数据缓存区
                                    MyAdapter adapter_new=new MyAdapter(data,getApplication());//Adapter作用将各种数据以合适的形式显示在View中给用户看
                                    listView.setAdapter(adapter_new);
                                    imageView_connect_status.setImageDrawable(getResources().getDrawable(R.drawable.light_off));
                                }
                            });
                            return;
                        }
                        runOnUiThread(new Runnable()
                        {
                            public void run() {
                                // TODO Auto-generated method stub
                                String recv_data=new String(buffer, 0, len);
                                textView_tip.setText("接收到："+recv_data);
                                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
                                Date time_date = new Date(System.currentTimeMillis());
                                add_display_recvdata("["+simpleDateFormat.format(time_date)+"]:"+recv_data);
                            }
                        });
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

}

